<?php
declare(strict_types=1);

namespace Zms\Request;

abstract class RequestAbstract
{
    /**
     * 请求方式
     * @var string
     */
    protected $method = 'GET';


    /**
     * 请求参数
     * @var null
     */
    protected $data = null;


    /**
     * 设置cookie
     * @var array
     */
    protected $cookies = [];


    /**
     * 请求头headers信息
     * @var array
     */
    protected $headers = [];

    /**
     * 超时时间,秒
     * @var int
     */
    protected $timeout = 30;


    /**
     * 设置请求方式为GET或POST。
     * @param string $method 请求的方法名，必须是'POST'或'GET'。
     * @return RequestAbstract 返回当前实例以支持链式调用。
     * @user zlf <zms-pro@qq.com> 2025/3/13
     */
    public function setMethod(string $method): RequestAbstract
    {
        $this->method = strtoupper($method);
        return $this;
    }

    /**
     * 设置请求数据
     * @param mixed $data
     * @return RequestAbstract 返回当前实例以支持链式调用。
     * @user zlf <zms-pro@qq.com> 2025/3/13
     */
    public function setData($data): RequestAbstract
    {
        $this->data = $data;
        return $this;
    }


    /***
     * @describe 设置COOKIE
     * @user zlf <zms-pro@qq.com> 2025/3/13
     * @param array $cookies
     * @return RequestAbstract
     */
    public function setCookies(array $cookies): RequestAbstract
    {
        $this->cookies = $cookies;
        return $this;
    }

    /**
     * @describe 批量设置Header
     * @user zlf <zms-pro@qq.com> 2025/3/13
     * @param array $headers 批量设置$headers，必须是字典类型,如['content-type'=>'application/json']。
     * @return $this
     */
    public function setHeaders(array $headers): RequestAbstract
    {
        $this->headers = $headers;
        return $this;
    }

    /**
     * @describe 单独设置Header
     * @user zlf <zms-pro@qq.com> 2025/3/13
     * @param string $name
     * @param string $value
     * @return $this
     */
    public function setHeader(string $name, string $value): RequestAbstract
    {
        $this->headers[$name] = $value;
        return $this;
    }


    /**
     * @describe 设置请求超时时间
     * @user zlf <zms-pro@qq.com> 2025/3/13
     * @param int $timeout
     * @return $this
     */
    public function setTimeout(int $timeout): RequestAbstract
    {
        $this->timeout = $timeout;
        return $this;
    }


    /**
     * @describe 设置请求链接
     * @user zlf <zms-pro@qq.com> 2025/3/13
     * @param string $url
     * @param array $query
     * @return string
     */
    protected function setLink(string $url, array $query = []): string
    {
        // 解析URL
        $parsedUrl = parse_url($url);

        // 如果URL中有查询字符串，则解析它
        if (isset($parsedUrl['query'])) {
            parse_str($parsedUrl['query'], $existingParams);
            // 合并新旧参数，新参数覆盖旧参数
            $query = array_merge($existingParams, $query);
        }
        // 生成新的查询字符串
        $newQuery = http_build_query($query);
        // 重新构建URL
        $scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'] . '://' : '';
        $host = $parsedUrl['host'] ?? '';
        $port = isset($parsedUrl['port']) ? ':' . $parsedUrl['port'] : '';
        $user = $parsedUrl['user'] ?? '';
        $pass = isset($parsedUrl['pass']) ? ':' . $parsedUrl['pass'] : '';
        $pass = ($user || $pass) ? "$pass@" : '';
        $path = $parsedUrl['path'] ?? '';
        $query = $newQuery ? "?$newQuery" : '';
        $fragment = isset($parsedUrl['fragment']) ? '#' . $parsedUrl['fragment'] : '';
        return implode('', [$scheme, $user, $pass, $host, $port, $path, $query, $fragment]);
    }

    /**
     * @describe 执行请求
     * @user zlf <zms-pro@qq.com> 2025/3/13
     * @param string $url
     * @param array $query
     * @return Result
     */
    abstract public function execute(string $url, array $query = []): Result;
}